/**
 * DSM - Distributed Search Manager
 * Author: gsingh@educationau.edu.au
 * $Revision: 1.3 $
 * $Date: 2007/01/03 23:07:46 $
 *
 * (C)opyright 2004 education.au pty limited (ABN 88 058 020 876) of
 * 178 Fullarton Road, Dulwich, South Australia 5065, Australia.
 *
 * This software was developed using funding and other support provided
 * by the Commonwealth of Australia's Department of Education, Science
 * and Training.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of Version 2 of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * See Version 2 of the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the
 *
 *    Free Software Foundation, Inc.,
 *    59 Temple Place, Suite 300,
 *    Boston, MA 02111-1307 USA.
 *
 * You can contact education.au pty limited by mail at
 *
 *    178 Fullarton Road,
 *    Dulwich, South Australia 5065,
 *    Australia
 *
 *    or
 *
 *    email opensource@educationau.edu.au.
 *
 */

package au.edu.educationau.opensource.dsm.adapters.contenthandler;

import java.util.ArrayList;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import au.edu.educationau.opensource.dsm.adapters.SearchAdapterProperties;
import au.edu.educationau.opensource.dsm.obj.ResultCategory;
import au.edu.educationau.opensource.dsm.obj.ResultMetadata;
import au.edu.educationau.opensource.dsm.obj.SearchResult;
import au.edu.educationau.opensource.dsm.worker.ResultSetUnifier;

public class DSMContentHandler extends DefaultHandler {
	private SearchResult result = new SearchResult();
	private ResultCategory cat = new ResultCategory();
	private ArrayList results = new ArrayList();
	private ArrayList categories = new ArrayList(5);
	private ArrayList metadata = new ArrayList(5);

	private StringBuffer titleBuffer = new StringBuffer();
	private StringBuffer descriptionBuffer = new StringBuffer();
	private StringBuffer linkBuffer = new StringBuffer();
	private StringBuffer categoryTitleBuffer = new StringBuffer();
	private StringBuffer categoryLinkBuffer = new StringBuffer();

	private short found = 0;

	private String currentElement = "";
	private String previousElement = "";
	private String token = "";
	private SearchAdapterProperties props = new SearchAdapterProperties();

	private boolean isItem = false;
	private boolean isCategory = false;

	/***/
	public short getFound() {
		return found;
	}

	public String getToken() {
		return token;
	}

	/***/
	public ArrayList getResults() {
		return results;
	}

	/**
	 * @param props
	 */
	public void setSearchAdapterProperties(SearchAdapterProperties props) {
		this.props = props;
	}

	/**
	 * @param ch
	 * @param ch_start
	 * @param ch_length
	 * @exception SAXException
	 */
	public void characters(char[] ch, int ch_start, int ch_length) throws SAXException {
		String val = String.copyValueOf(ch, ch_start, ch_length);

		// SUMMARY
		if (currentElement.equals("item")) {
			this.isItem = true;
		} else if (currentElement.equals("category")) {
			this.isItem = false;
			this.isCategory = true;
		} else if (currentElement.equals("found")) {
			try {
				this.found = Short.parseShort(val);
			} catch (NumberFormatException oe) {
			}
		} else if (currentElement.equals("token")) {
			this.token = token;
		}
		// ITEMS
		else if (currentElement.equals("link") && isItem) {
			linkBuffer.append(val);
		} else if (currentElement.equals("relevance")) {
			float relevance = 0f;
			try {
				relevance = Float.parseFloat(val);
			} catch (NumberFormatException oe) {
			}
			this.result.setRelevance(ResultSetUnifier.normaliseRelevance(relevance, props.getRelevanceMultiplier(), props.getRelevanceOffset()));
		} else if (currentElement.equals("title") && isItem) {
			titleBuffer.append(val);
		} else if (currentElement.equals("description")) {
			descriptionBuffer.append(val);
		} else if (currentElement.equals("rights")) {
			this.result.setRights(val);
		}
		// CATEGORIES
		else if (currentElement.equals("title") && isCategory) {
			categoryTitleBuffer.append(val);
		} else if (currentElement.equals("link") && isCategory) {
			this.cat.addPath(val);
		} else if (currentElement.equals("")) {
			if (previousElement.equals("description")) {
				descriptionBuffer.append(val);
			} else if (previousElement.equals("title") && isItem) {
				titleBuffer.append(val);
			} else if (previousElement.equals("link") && isItem) {
				linkBuffer.append(val);
			} else if (previousElement.equals("title") && isCategory) {
				categoryTitleBuffer.append(val);
			} else if (previousElement.equals("link") && isCategory) {
				categoryLinkBuffer.append(val);
			}
		}
		if (!currentElement.equals("")) {
			previousElement = currentElement;
		}

		// reset current element
		currentElement = "";
	}

	/**
	 * @param ch
	 * @param ch_start
	 * @param ch_length
	 * @exception SAXException
	 */
	public void ignorableWhitespace(char[] ch, int ch_start, int ch_length) throws SAXException {
	}

	/**
	 * @param uri
	 * @param localName
	 * @param qName
	 * @exception SAXException
	 */
	public void endElement(java.lang.String uri, java.lang.String localName, java.lang.String qName) throws SAXException {
		if (localName.equals("item")) {
			result.setDescription(descriptionBuffer.toString().trim());
			result.setLink(linkBuffer.toString().trim());
			result.setTitle(titleBuffer.toString().trim());
			result.setSource(props.getAdapterCode());
			result.setCollectionName(props.getDisplayTitle());
			metadata.trimToSize();
			ResultMetadata[] metadataArray = new ResultMetadata[metadata.size()];
			result.setResultMetadata((ResultMetadata[]) metadata.toArray(metadataArray));
			results.add(result);
			isItem = false;
			isCategory = false;
		} else if (localName.equals("category")) {
			this.cat.setName(categoryTitleBuffer.toString().trim());
			categories.add(cat);
		} else if (localName.equals("categories")) {
			categories.trimToSize();
			ResultCategory[] catArray = new ResultCategory[categories.size()];
			result.setResultCategories((ResultCategory[]) categories.toArray(catArray));
		}

	}

	/**
	 * @param target
	 * @param data
	 * @exception SAXException
	 */
	public void processingInstruction(String target, String data) throws SAXException {
	}

	/**
	 * @param uri
	 * @param localName
	 * @param qName
	 * @param attr
	 * @exception SAXException
	 */
	public void startElement(java.lang.String uri, java.lang.String localName, java.lang.String qName, Attributes attr) throws SAXException {
		this.currentElement = localName;
		if (localName.equals("item")) {
			result = new SearchResult();
			titleBuffer = new StringBuffer();
			descriptionBuffer = new StringBuffer();
			linkBuffer = new StringBuffer();
			metadata = new ArrayList(2);
			metadata.add(new ResultMetadata("source", attr.getValue("source")));
		} else if (localName.equals("category")) {
			cat = new ResultCategory();
			categoryTitleBuffer = new StringBuffer();
			categoryLinkBuffer = new StringBuffer();
		} else if (localName.equals("categories")) {
			cat = new ResultCategory();
			categories = new ArrayList(5);
		}
	}

}
